perm filename GRAFIX.SAI[PIC,HE] blob sn#430319 filedate 1979-04-01 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	entry
C00017 ENDMK
C⊗;
entry;
begin  "grafix"
  
  comment  August 2, 1978 .

  This module implements routines to handle graphics on the
  Tektronix terminal. Every attempt is made to provide routines
  that are device-independent.  The following is the prescription
  for producing displays. 
    clipinit  begindisplay  'display'  endisplay
  endcomment;

  comment   March 14, 1979

  This module has been updated to run at Stanford if the macro
  variable "STANFORD" is true. All attempts have been made to keep
  the changes as minimal as possible.

	Michael R. Lowry
  endcomment;

  define STANFORD="true";

  require  "define.sai"  source!file;
  IFC STANFORD THENC
  require  "grapin.sai"  source!file;
  ELSEC
  require  "gabbrv.sai"  source!file;
  ENDC

  integer  rbeg, cbeg;  ! Top left-hand corner of window to be
			displayed;
  integer  rend, cend;	! Bottom right-hand corner of window;
  integer  rwsz, cwsz;  ! Window size;
  integer  rowsz, colsz;	! Size of picture;
  integer  curr, curc;	! current position of cursor on the screen;
  integer  size;	! size defining the window;
  boolean  vectors;	! whether or not to draw st lines with 
			  arrow heads;
  real  arrowlength;	! length of the arrowheads;


  STRING  S;
  DEFINE  CLIPCHECK = "FALSE";

  internal  simple  procedure  resetwindow;
  ! Procedure to set the screen. Assumes correct size
    parameters in the variables rbeg, cbeg, rend, cend, and
    size.;
  vwindo(cbeg*1.0,size*1.33,-rend*1.0,size*1.0);

  internal  simple  boolean  procedure  rcok(integer r, c);
  ! Checks whether a point is within the window.;
  return(rbeg <= r <= rend and cbeg <= c <= cend);

  internal  simple  procedure  clipdsp(integer  r1, c1, r2, c2);
  begin  "clip"
  integer  cd1, cd2;
  real  theta, rrp, ccp, rrm, ccm;	! variables for displaying
					  arrow heads;
  integer  nswap;	! No of times swapping is done;
  
  ! Produces a clipped line inside the window. This same 
    implementation is given in 
    Newmann & Sproull, Principles of Interactive Computer Graphics,
    McGraw-Hill, 1973, p.124.;

    simple  integer  procedure  code(integer r, c);
    return(( if r < rbeg then '01 else (if r > rend then '10 else 0)) +
      (if c < cbeg then '100 else (if c > cend then '1000 else 0)));

    cd1 := code(r1,c1);  cd2 := code(r2,c2);  nswap := 0;
    IFC  CLIPCHECK  THENC
    PRINT("CODES",CD1," ",CD2,CRLF);
    s := INTTY;  ENDC
    while  not(cd1 = cd2 = 0)  do
    begin
      IFC  CLIPCHECK  THENC
      IF  CD1 LAND CD2  THEN
      PRINT(" NOT VISIBLE",R1," ",C1," ",R2," ",C2,CRLF);
      s := INTTY;  ENDC
      if  cd1 land cd2  then  return;
      if  cd1 = 0  then  
      begin
        cd1 swap cd2;  r1 swap r2;  c1 swap c2;  nswap := nswap + 1;
      end;
      if  cd1 land '1  then
      begin
        c1 := c1 + (c2-c1)*(rbeg-r1)/(r2-r1);  r1 := rbeg;
      end  else
      if  cd1 land '10  then
      begin
        c1 := c1 + (c2-c1)*(rend-r1)/(r2-r1);  r1 := rend;
      end  else
      if  cd1 land '100  then
      begin
        r1 :=  r1 + (r2-r1)*(cbeg-c1)/(c2-c1);  c1 := cbeg;
      end  else
      if  cd1 land '1000  then
      begin
        r1 :=  r1 + (r2-r1)*(cend-c1)/(c2-c1);  c1 := cend;
      end;
      cd1 := code(r1,c1);
    end;

    IFC  CLIPCHECK  THENC
    PRINT(" CLIPPED LINE",R1," ",C1," TO ",R2," ",C2,CRLF);
    s := INTTY;
    ELSEC
      movea(1.0*c1,-1.0*r1);  drawa(1.0*c2,-1.0*r2);
      if  vectors  then
      begin
        if  not even(nswap)  then
        begin
          r1 swap r2;  c1 swap c2;
        end;
        theta := myatan(c2-c1,r2-r1);
        rrp := cosd(theta+135) * arrowlength;
        ccp := sind(theta+135) * arrowlength;
        rrm := - ccp;  ccm := rrp;
        drawa(1.0*(c2+ccp),-1.0*(r2+rrp));
        movea(1.0*(c2+ccm),-1.0*(r2+rrm));
        drawa(1.0*c2,-1.0*r2);
      end;
    ENDC
  end  "clip" ;

  internal  sIMPLE PROCEDURE ARDSTR(STRING sTR);
    IFC STANFORD THENC
    begin
	putext(str);
    end;

    ELSEC
    BEGIN
    INTEGER I,CHA;
    FOR I←1 sTEP 1 UNTIL LENGTH(STR) DO
	BEGIN CHA←STR[I FOR 1];
	IF CHA='12 THEN LINEF ELSE IF CHA='15 THEN CARTN
	    ELSE ANCHO(CHA);
	END;
    END;
    ENDC

  internal  simple  procedure  dcrlf;
  begin
  ! Produces an equivalent of carriage-return and line-feed for
    alphameric display.;
    curc ← cbeg;
    curr := curr + (3*size)/100;
    movea(1.0*curc,-1.0*curr);
  end;

  internal  simple  procedure  movecursor(integer r, c);
  begin
  ! Moves cursor on the screen to the designated point.;
    curr := r;  curc := c;  movea(1.0*c,-1.0*r);
  end;

  INTERnal  simple  procedure  legend(string pic);
  begin
  integer  sz;
  ! Procedure to produce a legend on the Tektronix terminal.
    The legend is produced in the upper right-hand corner of the
    screen.;
    sz := 100;  curr := 5;  curc := 76;
    vwindo(0.0,1.0*sz,-1.0*sz,1.0*sz);
    movecursor(curr,curc);  ardstr(pic);  dcrlf;  dcrlf;
    ardstr("top left corner: ");  dcrlf;  
    ardstr(cvs(rbeg)&" "&cvs(cbeg));  dcrlf;  dcrlf;
    ardstr("window: ");  dcrlf;
    ardstr(cvs(rwsz)&" X "&cvs(cwsz));  dcrlf;  dcrlf;
  end;

  internal  simple  procedure  linelegend(string s);
  begin
  ! Produces a single line of legend, whatever it may be.;
    ardstr(s);  dcrlf;
  end;

  simple  procedure  border;
  begin
  ! Bordering the picture on the terminal screen.;
  ! produces border on the terminal;
      movea(1.0*cbeg,-1.0*rbeg);
      drawa(1.0*cbeg,-1.0*rend);
      drawa(1.0*cend,-1.0*rend);
      drawa(1.0*cend,-1.0*rbeg);
      drawa(1.0*cbeg,-1.0*rbeg);
  end;

  internal  simple  procedure  cliptest;
  begin
  ! Procedure to test 
		procedure clipdsp
    defined above.;
  integer  r1, c1, r2, c2;
    iprmpt(" rbeg",rbeg);  iprmpt(" rend",rend);
    iprmpt(" cbeg",cbeg);  iprmpt(" cend",cend);
    do  begin
      iprmpt(" r1",r1);  iprmpt(" c1",c1);
      iprmpt(" r2",r2);  iprmpt(" c2",c2);
      clipdsp(r1,c1,r2,c2);
      print(r1," ",c1," ",r2," ",c2," ",crlf);
    end  until  false;
  end;

  internal  simple  procedure  clipinit(integer r, c);
  begin
  ! Initialising this module.;
    rowsz := r;  colsz := c;  rbeg := 1;  cbeg := 1;
    size := r;  if  c > size  then  size := c;
    rwsz := r;  cwsz := c;  rend := r;  cend := c;
    vectors := false;
  end;

  simple  procedure  graphicswindow;
  begin
    do  begin
      print(" specify window.",crlf);
      iprmpt(" row begin",rbeg);  iprmpt(" col begin",cbeg);
      rwsz := rowsz - rbeg + 1;  cwsz := colsz - cbeg+ 1;
      iprmpt(" no of rows",rwsz);  iprmpt(" no of cols",cwsz);
      rend := rbeg + rwsz - 1;  cend := cbeg + cwsz - 1;
    end  until  1 <= rbeg <= rowsz and 1 <= rend <= rowsz 
           and  1 <= cbeg <= colsz and 1 <= cend <= colsz;
    size := rwsz;  if  cwsz > rwsz  then  size := cwsz;
    arrowlength := size/128.0;
  end;

  simple  procedure  startdisplay;
  begin
  ! Make sure you set up the size parameters all right ;
    pctr(0);  initt(450);
    resetwindow;  border;
    movecursor(rbeg,rend);
  end;

  internal  simple  procedure  endisplay;
  begin
    linelegend(date);  linelegend(ttime);
    movecursor(rend,cend);
  endpct;
  end;

  internal  simple  procedure  dashedline(integer fr,fc,tr,tc);
  begin
  ! Given from and to coordinates, produces a dashed line.;
    movea(1.0*fc,-1.0*fr);  dasha(1.0*tr,-1.0*tc);
    curr := tr;  curc := tc;
  end;

  internal  simple  procedure  begindisplay;
  begin
    bprmpt(" Vectors ?",vectors);
    graphicswindow;  startdisplay;
  end;

  internal  simple  procedure  drawline(integer r, c);
  begin
  ! Draws a line from wherever the cursor is to the point 
    specified. Cursoris moved also;
    clipdsp(curr,curc,r,c);  curr := r;  curc := c;
  end;

  INTERnal  simple  procedure  dispid(integer id, r, c);
  begin
  ! Displays an integer at the given coordinates.;
    if  rcok(r,c)  then
    begin
      movecursor(r,c);  ardstr(cvs(id));
    end;
  end;

  internal  simple  procedure  clipoint(integer r,c);
  begin
  ! displays a point, if within the window.;
  if  rcok(r,c)  then  
	    pointa(1.0*c,-1.0*r);
  end;

  internal  simple  procedure  getwindow(reference integer r1,c1,r2,c2);
  begin
  ! Returns the top left-hand and bottom right-hand corners of the
  current window;
    r1 := rbeg;  c1 := cbeg;  r2 := rend;  c2 := cend;
  end;

  internal  simple  procedure  drawvectors;
  vectors := true;

  internal  simple  procedure  novectors;
  vectors := false;

end  "grafix";